import TextEditor from "@/modules/model/comps/station/sider/attribute/propertyEditors/modals/TextEditor.vue";
import { actionManager } from "@/action/ActionManager";
import { SlotEditKey } from "@/constants/constants";
import { CreatePropertyModelTreeSelect } from "@/modules/model/actions/project/CreatePropertyModelTreeSelect";
import { modelService } from "@/modules/model/service";
import { propertyUtil } from "../PropertyUtil";
import { InstanceSlotData, ClassifierData } from "../types";
import { SlotsPaneModel } from "./SlotsPaneModel";
import { ActionKey } from "@/action/ActionKey";
import { BusEvent, PropertyDataType } from "@/constants/Enums";
import { AttributeTabsData } from "./AttributeTabsModel";
import { DateAndTimeSettingWindow } from "@/config/customSystemConfig/customWindows/dateAndTimeSettingWindow";
import { BannerPaneModel } from "./BannerPaneModel";
import { reactive } from "vue";

const dateTypePropertySt = [
  "UAF::Architecture Management::Taxonomy::ActualState::endDate",
  "UAF::Architecture Management::Taxonomy::ActualState::startDate",
  "UAF::Projects::Roadmap::ActualProjectMilestone::endDate",
  "UAF::Personnel::Traceability::ResponsibleFor::endDate",
  "UAF::Personnel::Traceability::ResponsibleFor::startDate",
  "UAF::Standards::Taxonomy::Standard::mandatedDate",
  "UAF::Standards::Taxonomy::Standard::retiredDate",
  "UAF::Actual Resources::Connectivity::FillsPost::endDate",
  "UAF::Actual Resources::Connectivity::FillsPost::startDate"
];

export class TagsPaneModel extends SlotsPaneModel {
  specificationKey = SlotEditKey.TagValue;
  bannerModel = reactive(new BannerPaneModel(this));
  async loadTable() {
    const { projectId, modelId } = this.tabsModel.data;
    if (!projectId || !modelId) return;

    this.loading = true;
    try {
      const res = await modelService.queryAllStereotype(projectId, modelId);
      const rows = res as ClassifierData[];
      rows.forEach(row => {
        row.isExpand = true;
        row.slots = [];
      });

      await Promise.all(
        rows.map(row => {
          return this.loadSlots(row);
        })
      );

      this.tableData = rows.filter(it => it.slots.length);

      if (this.activeSlotValueId) {
        const value = this.getActiveSlotValue();
        if (!value) {
          this.activeSlotValueId = undefined;
        }
      }
    } finally {
      this.loading = false;
    }
    this.loaded = true;
  }

  async loadSlots(row: ClassifierData): Promise<void> {
    const slots = await modelService.queryAllProperty(this.tabsModel.projectId, this.tabsModel.data.modelId!, row.id!);

    row.slots = slots;
  }

  async updateSlotValue(row: InstanceSlotData, values: (string | number | boolean | null)[]) {
    await propertyUtil.updateSlotValue(app.activeProject!.id, this.tabsModel.modelId!, row, values);
  }

  async addSlotValue(data: InstanceSlotData) {
    const values = data.values.map(item => item.value);
    if (dateTypePropertySt.includes(data.propertyId)) {
      await DateAndTimeSettingWindow.popup({ projectId: this.tabsModel.projectId }, async ({ success, result }) => {
        if (success) {
          const { timeLine, date } = result;
          await modelService.setTimeLine(this.tabsModel.projectId, this.tabsModel.data.modelId!, timeLine, data.propertyId, date);
        }
        DateAndTimeSettingWindow.done();
      });
      return;
    }
    if (
      data.dataType == PropertyDataType.STRING ||
      data.dataType == PropertyDataType.REAL ||
      data.dataType == PropertyDataType.INTEGER ||
      data.dataType == PropertyDataType.UNLIMITEDNATURAL
    ) {
      let hasError = false;
      const needValidTypes: Array<any> = [PropertyDataType.REAL, PropertyDataType.INTEGER, PropertyDataType.UNLIMITEDNATURAL];
      const realReg = /^[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?$/;
      const integerReg = /^[-+]?\d+$/;

      const newText = await TextEditor.popup({
        title: data.name,
        text: "",
        validText: async (text: string) => {
          if (!needValidTypes.includes(data.dataType)) {
            return true;
          }
          let reg = data.dataType === PropertyDataType.INTEGER ? integerReg : realReg;
          if (!reg.test(text)) {
            await app.$notify({
              type: "error",
              title: "提示",
              message: "类型不匹配"
            });
            return false;
          } else {
            return true;
          }
        }
      }).catch((err: any) => {
        err && console.error(err);
        hasError = true;
      });

      if (hasError) return;
      values.push(newText);
      await this.updateSlotValue(data, values);
    } else if (data.dataType == PropertyDataType.INSTANCE) {
      const row = {
        ...data,
        checkMethod: "checkTypeValueByProperty",
        projectId: this.tabsModel.projectId,
        key: this.specificationKey,
        modelId: data.propertyId,
        parentId: this.tabsModel.data.modelId,
        isMultiplicity: true
      };
      const action = actionManager.getAction(ActionKey.CreatePropertyModelTreeSelect) as CreatePropertyModelTreeSelect;

      action.createProperty(row, "attrSlots", "插槽");
    } else if (data.dataType == PropertyDataType.BOOLEAN) {
      values.push(false);
      await this.updateSlotValue(data, values);
    } else if (propertyUtil.isRowDataTypeEnum(data)) {
      const firstValue = data.items?.[0]?.value;
      if (firstValue) {
        values.push(firstValue);
        await this.updateSlotValue(data, values);
      }
    }
  }

  async deleteSlotValue(data: InstanceSlotData) {
    const slotValue = this.getActiveSlotValue();
    if (!slotValue) {
      return;
    }
    const values = data.values.filter(it => it.id !== this.activeSlotValueId).map(it => it.value);
    await this.updateSlotValue(data, values);

    this.activeSlotValueId = undefined;
  }

  async editSlotValue(data: InstanceSlotData) {
    const slotValue = this.getActiveSlotValue();
    if (!slotValue) {
      return;
    }

    if (dateTypePropertySt.includes(data.propertyId)) {
      await DateAndTimeSettingWindow.popup(
        { projectId: this.tabsModel.projectId, date: slotValue.value as string },
        async ({ success, result }) => {
          if (success) {
            const { timeLine, date } = result;
            await modelService.setTimeLine(this.tabsModel.projectId, this.tabsModel.data.modelId!, timeLine, data.propertyId, date);
          }
          DateAndTimeSettingWindow.done();
        }
      );
      app.$bus.emit(BusEvent.REFRESH_SLOT, this.tabsModel.data.modelId);
      return;
    }

    let hasError = false;
    const needValidTypes: Array<any> = [PropertyDataType.REAL, PropertyDataType.INTEGER, PropertyDataType.UNLIMITEDNATURAL];
    const realReg = /^[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?$/;
    const integerReg = /^[-+]?\d+$/;

    const newText = await TextEditor.popup({
      title: data.name,
      text: slotValue.value,
      validText: async (text: string) => {
        if (!needValidTypes.includes(data.dataType)) {
          return true;
        }
        let reg = data.dataType === PropertyDataType.INTEGER ? integerReg : realReg;
        if (!reg.test(text)) {
          await app.$notify({
            type: "error",
            title: "提示",
            message: "类型不匹配"
          });
          return false;
        } else {
          return true;
        }
      }
    }).catch((err: any) => {
      err && console.error(err);
      hasError = true;
    });

    if (hasError) return;

    const index = data.values.findIndex(it => it.id === slotValue.id);
    const values = data.values.map(it => it.value);
    values[index] = newText;
    await this.updateSlotValue(data, values);

    app.$bus.emit(BusEvent.REFRESH_SLOT, this.tabsModel.data.modelId);
  }

  async editTreeSlot(data: InstanceSlotData, model: AttributeTabsData) {
    // console.log('data:', data);
    //

    const action = actionManager.getAction(ActionKey.ModelStructureAction);
    action?.run(data, model);
  }
}
